package com.heima.wemedia.service.impl;


import com.alibaba.fastjson.JSON;
import com.heima.common.aliyun.GreenImageUploadScan;
import com.heima.common.aliyun.GreenTextScan;
import com.heima.common.aliyun.util.AuditResultDTO;
import com.heima.common.tess4j.Tess4jClient;
import com.heima.common.util.SensitiveWordUtil;
import com.heima.file.service.MinioService;
import com.heima.model.media.dtos.WmNewsContentItem;
import com.heima.model.media.dtos.WmNewsDto;
import com.heima.wemedia.entity.WmNews;
import com.heima.wemedia.entity.WmSensitive;
import com.heima.wemedia.service.WmAuditService;
import com.heima.wemedia.service.WmNewsService;
import com.heima.wemedia.service.WmSensitiveService;
import lombok.extern.slf4j.Slf4j;
import net.sourceforge.tess4j.TesseractException;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

import static com.heima.common.Constants.THREAD_POOL_NAME;

@Slf4j
// @Service
public class WmAuditServiceImpl implements WmAuditService {

    @Autowired
    private GreenTextScan textAudit;

    @Autowired
    private GreenImageUploadScan imageAudit;

    @Autowired
    @Lazy //解决循环依赖
    private WmNewsService newsService;

    @Autowired
    MinioService minioService;

    @Autowired
    private WmSensitiveService sensitiveService;

    @Autowired
    private Tess4jClient tess4jClient;

    @Override
    @Async(THREAD_POOL_NAME)
    public void asyncAudit(Integer wmUserId, WmNewsDto dto) {
        log.info("开始异步审核。。。。。");
        // 阿里云文本审核
        // 标题
        String title = dto.getTitle();
        // 标签
        String label = dto.getLabels();
        //正文中的文本
        List<WmNewsContentItem> wmNewsContentItems = JSON.parseArray(dto.getContent(), WmNewsContentItem.class);
        String text = wmNewsContentItems.stream().filter(item -> item.getType().equals("text")).map(item -> item.getValue()).collect(Collectors.joining("--"));
        // 标题 + 标签 + 正文中的文本
        String auditText = title + "--" + label + "--" +text;
        try {
            AuditResultDTO auditResultDTO = textAudit.greenTextScan(auditText);
            if(auditResultDTO.isAuditFail()){
                // 审核失败,改状态，填充失败的理由
                WmNews toBeUpdate = new WmNews();
                toBeUpdate.setId(dto.getId());
                toBeUpdate.setStatus(2);//TODO
                toBeUpdate.setReason(auditResultDTO.getReason());
                newsService.updateById(toBeUpdate);
                return;
            }else if(auditResultDTO.isAuditReview()){
                // 审核不确定，转人工
                WmNews toBeUpdate = new WmNews();
                toBeUpdate.setId(dto.getId());
                toBeUpdate.setStatus(3);//TODO
                toBeUpdate.setReason(auditResultDTO.getReason());
                newsService.updateById(toBeUpdate);
                return;
            }
        } catch (Exception e) {
            log.error("阿里云文本审核异常：{}", ExceptionUtils.getStackTrace(e));
            return;
        }
        //阿里云图片审核, 解析正文和封面中的图片地址，从minio下载得到文件的字节数组
        // 取正文图
        List<String> contentImageUrlList = wmNewsContentItems.stream().filter(item -> item.getType().equals("image")).map(item -> item.getValue()).collect(Collectors.toList());
        // 取封面图
        List<String> coverImageUrlList = dto.getImages();
        // 正文图可能跟封面图是同一张图，去重一下
        Set<String> noRepeateUrlList = new HashSet<>();
        if(!CollectionUtils.isEmpty(contentImageUrlList)){
            noRepeateUrlList.addAll(contentImageUrlList);
        }
        if(!CollectionUtils.isEmpty(coverImageUrlList)){
            noRepeateUrlList.addAll(coverImageUrlList);
        }
        List<byte[]> imageByteList = new ArrayList<>(noRepeateUrlList.size());
        if(!CollectionUtils.isEmpty(noRepeateUrlList)){
            // 从minio下载
           for(String url : noRepeateUrlList){
               byte[] imageBytes = minioService.downLoadFile(url);
               if(imageBytes != null && imageBytes.length > 0){
                   imageByteList.add(imageBytes);
               }
           }
        }
        if(!CollectionUtils.isEmpty(imageByteList)){
            try {
                AuditResultDTO auditResultDTO = imageAudit.imageScan(imageByteList);
                if(auditResultDTO.isAuditFail()){
                    // 审核失败,改状态，填充失败的理由
                    WmNews toBeUpdate = new WmNews();
                    toBeUpdate.setId(dto.getId());
                    toBeUpdate.setStatus(2);//TODO
                    toBeUpdate.setReason(auditResultDTO.getReason());
                    newsService.updateById(toBeUpdate);
                    return;
                }else if(auditResultDTO.isAuditReview()){
                    // 审核不确定，转人工
                    WmNews toBeUpdate = new WmNews();
                    toBeUpdate.setId(dto.getId());
                    toBeUpdate.setStatus(3);//TODO
                    toBeUpdate.setReason(auditResultDTO.getReason());
                    newsService.updateById(toBeUpdate);
                    return;
                }
            } catch (Exception e) {
                log.error("阿里云图片审核异常：{}", ExceptionUtils.getStackTrace(e));
                return;
            }
        }
        // 文本敏感词审核
        // 把数据库中所有的敏感词都查询出来，feign调用 TODO
        List<WmSensitive> sensitiveList = sensitiveService.list();
        List<String> senesitiveWords = null;
        if(!CollectionUtils.isEmpty(sensitiveList)){
            senesitiveWords = sensitiveList.stream().map(WmSensitive::getSensitives).collect(Collectors.toList());
            Map<String, Integer> resultMap = SensitiveWordUtil.matchWords(senesitiveWords, auditText);
            if(resultMap.size() > 0){
                // 说明敏感词审核不通过，改状态，填充失败的理由
                WmNews toBeUpdate = new WmNews();
                toBeUpdate.setId(dto.getId());
                toBeUpdate.setStatus(2);//TODO
                toBeUpdate.setReason(resultMap.keySet().stream().collect(Collectors.joining(",")));
                newsService.updateById(toBeUpdate);
                return;
            }
        }
        // 图片文字识别，敏感词审核, 把图片中的文本提取出来，做文本的敏感词审核
        if(!CollectionUtils.isEmpty(imageByteList) && !CollectionUtils.isEmpty(senesitiveWords)){
            try {
                for(byte[] imageBytes : imageByteList){
                    BufferedImage bufferedImage = ImageIO.read(new ByteArrayInputStream(imageBytes));
                    String imageText = tess4jClient.doOCR(bufferedImage);
                    Map<String, Integer> resultMap = SensitiveWordUtil.matchWords(senesitiveWords, imageText);
                    if(!CollectionUtils.isEmpty(resultMap)){
                        // 说明敏感词审核不通过，改状态，填充失败的理由
                        WmNews toBeUpdate = new WmNews();
                        toBeUpdate.setId(dto.getId());
                        toBeUpdate.setStatus(2);//TODO
                        toBeUpdate.setReason(resultMap.keySet().stream().collect(Collectors.joining(",")));
                        newsService.updateById(toBeUpdate);
                        return;
                    }
                }
            } catch (Exception e) {
                log.error("图片敏感词审核异常：{}", ExceptionUtils.getStackTrace(e));
                return;
            }
        }
        // 审核通过， 改状态， 发布文章
        WmNews toBeUpdate = new WmNews();
        toBeUpdate.setId(dto.getId());
        toBeUpdate.setStatus(8);//TODO
        toBeUpdate.setReason("");
        newsService.updateById(toBeUpdate);

    }
}
